package com.bstek.uflo.designer.security;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.springframework.util.StringUtils;

import com.bstek.dorado.annotation.PropertyDef;
import com.bstek.uflo.designer.model.Mapping;
import com.bstek.uflo.designer.model.Shape;
import com.bstek.uflo.designer.security.annotation.SecurityAttribute;

/**
 * @author matt.yao@bstek.com
 * @since 1.0
 */
public abstract class ShapeAuthorizeAttribute implements AuthorizeAttribute {

	public List<Mapping> getAttributes() {
		List<Mapping> mappingList = new ArrayList<Mapping>();
		Stack<Class<?>> stack = getShapeClassStack();
		while (!stack.isEmpty()) {
			Class<?> clazz = stack.pop();
			Field[] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				String key = null;
				String label = null;
				SecurityAttribute securityAttribute = field.getAnnotation(SecurityAttribute.class);
				if (securityAttribute != null) {
					key = securityAttribute.key();
					label = securityAttribute.label();
					if (!StringUtils.hasText(key)) {
						key = field.getName();
					}
					if (!StringUtils.hasText(label)) {
						PropertyDef propertyDef = field.getAnnotation(PropertyDef.class);
						if (propertyDef != null) {
							label = propertyDef.label();
						}
						if (!StringUtils.hasText(label)) {
							label = key;
						}
					}
					mappingList.add(new Mapping(key, label));
				}
			}
		}
		return mappingList;
	}

	private Stack<Class<?>> getShapeClassStack() {
		Stack<Class<?>> stack = new Stack<Class<?>>();
		this.buildShapeClass(getShapeClass(), stack);
		return stack;
	}

	private void buildShapeClass(Class<?> clazz, Stack<Class<?>> stack) {
		stack.push(clazz);
		Class<?> superClazz = clazz.getSuperclass();
		if (!superClazz.equals(Shape.class)) {
			this.buildShapeClass(superClazz, stack);
		}
	}

	public abstract boolean support(String name);

	public abstract Class<?> getShapeClass();
}
